home *** CD-ROM | disk | FTP | other *** search
/ Best Tools for JAVA / Best Tools for JAVA.iso / JAVA_ALL / JAVA_UTL / HYPERPRO / SRC / PVS / HYPERBOL / HYPERBOL.JAV < prev    next >
Encoding:
Text File  |  1996-09-14  |  6.7 KB  |  225 lines

  1. package PVS.Hyperbolic;
  2. //
  3. // Copyright (C) 1996 by Vladimir Bulatov <V.Bulatov@ic.ac.uk>.  
  4. //        All rights reserved.
  5. //
  6. // Redistribution and use in source and binary forms, with or without
  7. // modification, are permitted provided that the following conditions
  8. // are met:
  9. // 1. Redistributions of source code must retain the above copyright
  10. //    notice, this list of conditions and the following disclaimer.
  11. // 2. Redistributions in binary form must reproduce the above copyright
  12. //    notice, this list of conditions and the following disclaimer in the
  13. //    documentation and/or other materials provided with the distribution.
  14. //
  15. // THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
  16. // ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
  17. // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
  18. // ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
  19. // FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
  20. // DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
  21. // OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
  22. // HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
  23. // LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
  24. // OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  25. // SUCH DAMAGE.
  26.  
  27. import PVS.Utils.MathExt;
  28.  
  29. public class Hyperbolic {
  30.     
  31.   static final double EPS = 1.e-4;
  32.  
  33.   // switch to draw lines instead of arcs
  34.   public static boolean fastLines = false; 
  35.  
  36.   /**
  37.     doTranslate() does hyperbolic translation of z 
  38.     This translation moves center of hyperbolic plane into point p.
  39.    */
  40.   static Complex c1 = new Complex(),c2 = new Complex(),c3 = new Complex();
  41.  
  42.   public static void doTranslate(Complex z,Complex p){ // z = (z+p)/(1+(p*)*z)
  43.     c1.add(z,p);
  44.     c2.conj(p);
  45.     c3.mul(c2,z);
  46.     c3.add(1);
  47.     z.div(c1,c3);
  48.   }
  49.  
  50.   /**
  51.     doTransform() does most common hyperbolic motion:
  52.     rotation on t.teta over center and translation over t.p;
  53.    */
  54.   public static void doTransform(Complex z,HTransform t){ 
  55.     // z = (z*teta+p)/(1+(p*)*z)
  56.     c1.mul(z,t.teta);
  57.     c1.add(t.p);
  58.     c2.conj(t.p);
  59.     c3.mul(c2,z);
  60.     c3.add(1);
  61.     z.div(c1,c3);
  62.   }
  63.  
  64.   /**
  65.     does composition of two transformations: t1 and t2
  66.     and puts result in t1
  67.    */
  68.   public static void doTransform(HTransform t1,HTransform t2){
  69.     //teta = (teta1*t2+teta1*p1^*p2)/(1+teta2*p1*p2^);
  70.     //peta = (teta2*p1+p2)/(1+teta2*p1*p2^);
  71.     
  72.     // denominator
  73.     c1.set(t2.p).conj().mul(t1.p).mul(t2.teta).add(1.);
  74.  
  75.     c2.mul(t2.teta,t1.p).add(t2.p);
  76.     c3.set(t1.p).conj().mul(t2.p).add(t2.teta).mul(t1.teta);
  77.  
  78.     t1.p.div(c2,c1);
  79.     t2.teta.div(c3,c1);
  80.     t2.teta.div(t2.teta.abs());
  81.   }
  82.  
  83.   static boolean ParallelArc(Complex z1, Complex z2){
  84.     double ab1 = z1.abs2(),ab2 = z2.abs2();
  85.     double ar1 = z1.arg(),ar2 = z2.arg();
  86.     return ((ab1 < EPS || ab2 < EPS) ||
  87.         ((ab1 >= EPS && ab2 >= EPS) &&
  88.          ((Math.abs(ar1-ar2) < EPS || (Math.abs(ar1-ar2-Math.PI) < EPS) ||
  89.            (Math.abs(ar1-ar2+Math.PI) < EPS)))));
  90.   }
  91.   
  92.   /**
  93.     Euclidean distance between two points
  94.    */
  95.   public static double EuclDistance(Complex z1, Complex z2){
  96.     return Math.sqrt(MathExt.sqr(z1.re-z2.re)+MathExt.sqr(z1.im-z2.im));
  97.   }
  98.  
  99.   /**
  100.     Hyperbolic distance between two points
  101.    */
  102.   public static double HyperDistance(Complex z1, Complex z2){
  103.     // 2*atanh((z1-z2)/(1-z1*z2^));
  104.     c2.set(z2); c2.conj();c2.mul(z1);c2.neg();c2.add(1.); 
  105.     c1.sub(z1,z2); c1.div(c3);
  106.     return 2.*MathExt.atanh(c1.abs());
  107.   }
  108.  
  109.   /**
  110.     Hyperbolic distance of euqclidean point from origin
  111.    */
  112.   public static double HyperDistance(Complex z){
  113.     // 2*atanh(z);
  114.     return e2h(z.abs());
  115.   }
  116.  
  117.   /**
  118.     Hyperbolic distance of euqclidean point from origin
  119.    */
  120.   public static double e2h(double x){
  121.     // 2*atanh(x);
  122.     return 2.*MathExt.atanh(x);
  123.   }
  124.   
  125.   /**
  126.     Euclidean distance of hyperbolic point from origin
  127.    */
  128.   public static double h2e(double h){  
  129.     return MathExt.tanh(h*0.5);
  130.   }
  131.  
  132.   /**
  133.     Reflects point in givent arc.
  134.    */  
  135.   public static void reflect(Complex p,Arc arc){
  136.     if(arc.r == 0.0){ // strait line
  137.       double qx = arc.x, qy = arc.y, px = arc.start, py = arc.angle;
  138.       double denom = MathExt.sqr(qx-px)+ MathExt.sqr(qy-py);
  139.       double t = py*(qx-p.re)-qy*(px-p.re)+p.im*(px-qx);
  140.       p.set(p.re+2*(py-qy)*t, p.im+21*(px+qx)*t);
  141.     } else {
  142.       double denom = MathExt.sqr(p.re-arc.x) + MathExt.sqr(p.im-arc.y);
  143.       double r2 = arc.r*arc.r;
  144.       p.set(arc.x + r2*(p.re-arc.x)/denom, arc.y + r2*(p.im-arc.y)/denom);
  145.     }
  146.   }
  147.  
  148.   /**
  149.     Produces segment of hyperbolic cyrcle, which connects z1 and z2.
  150.    */  
  151.   static Complex ccenter = new Complex(),t2 = new Complex(),t1 = new Complex();
  152.   public static Arc getArc(Complex z1, Complex z2, Arc segment){
  153.     if(segment == null)
  154.       segment = new Arc();
  155.  
  156.     if(ParallelArc(z1,z2)){
  157.       segment.r = 0.0;
  158.       segment.x = z1.re;
  159.       segment.y = z1.im;
  160.       segment.start = z2.re;
  161.       segment.angle = z2.im;
  162.       return segment;
  163.     }
  164.     double s1 = 1 + z1.abs2(), s2 = 1 + z2.abs2();
  165.     double norm = 1/(2*(z1.re*z2.im - z2.re*z1.im));          
  166.     ccenter.set((s1*z2.im-s2*z1.im)*norm,
  167.         -(s1*z2.re-s2*z1.re)*norm);
  168.     double cradius = EuclDistance(ccenter,z2);
  169.  
  170.     double angle1, angle2, minang, angle;
  171.  
  172.     t1.set(z1); t1.sub(ccenter); angle1= t1.arg(); //Arg(z1-ccenter);
  173.     t2.set(z2); t2.sub(ccenter); angle2= t2.arg(); //Arg(z2-ccenter);
  174.     
  175.     if(angle1 < 0.0) angle1 += 2.0*Math.PI;
  176.     if(angle2 < 0.0) angle2 += 2.0*Math.PI;
  177.     minang = angle1;//(angle1 < angle2) ? angle1 : angle2;
  178.     angle = angle2 - angle1;//(angle1 > angle2) ? angle1-angle2 : angle2-angle1;
  179.     if(angle > Math.PI)
  180.       angle -= 2.0*Math.PI;
  181.     else if(angle < -Math.PI){
  182.       angle += 2.0*Math.PI;
  183.     }
  184.     segment.x = ccenter.re;
  185.     segment.y = ccenter.im;
  186.     segment.r = cradius;
  187.     segment.start = minang;
  188.     segment.angle = angle;
  189.     return segment;
  190.  
  191.   }
  192.  
  193.   /** 
  194.     Draw a geodesic arc which goes from a given point z1 to a given point z2 
  195.     */
  196.   static Arc arc = new Arc();
  197.   public static void drawGeodArc(Graphics2d g, Complex z1, Complex z2){
  198.     if(fastLines)
  199.       g.drawLine(z1.re, z1.im, z2.re, z2.im);
  200.     else {
  201.       getArc(z1,z2,arc);
  202.       g.drawArc(arc);
  203.     }
  204.   }
  205.  
  206.   public static void drawPoly(Graphics2d g, Complex[] vert, int nvert){
  207.     Complex c = vert[nvert-1];
  208.     for(int i=0; i < nvert; i++){
  209.       drawGeodArc(g,c,vert[i]);
  210.       c = vert[i];
  211.     }
  212.   }
  213.  
  214.   public static void fillPoly(Graphics2d g, Complex[] vert, int nvert){
  215.     Complex c = vert[nvert-1];
  216.     Arc[] arc = new Arc[nvert];
  217.     for(int i=0; i < nvert; i++){
  218.       arc[i] = getArc(c,vert[i],null);
  219.       c = vert[i];
  220.     }
  221.     g.fillArcs(arc);
  222.   }
  223.   
  224. }
  225.